package bittwiddling;

/*
 * // Theoretical points
	1. Difference between logical (or unsigned) and arithmetic (or signed) shift: http://en.wikipedia.org/wiki/Bitwise_operation
	2. Also check what is "sign extension". That's why you'll get -1>>'any number' = -1
	3. Valid shift values are only from 0 and 31 for int and 0 to 63 for long. If values are not in this range, these are subjected to 'mod 32' (in case of int) e.g. -1 >>> 32 = -1 >>> 0 = -1.
	(this way of mod, using bit-twiddling, works only when divisor is power of two)
	Details: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.19
	4. still not clear why '>>>' doesn't lead to overflow. I haven't found any material yet which suggests that 'int' is converted to 'long'.
 * 
 * */

public class ShiftOperations {

	public static void main(String[] args){
		checkUnsignedOperator();
		//checkSignExtension();

	}
	

	public static void checkUnsignedOperator(){
		
		int a = 2000000000;
		int b = 2000000000;
		int c = 2000000000;
		int d = 2000000000;

		// open issue
		// Not clear why '>>>' doesn't lead to overflow on the left side
		
		// signed operator
		System.out.println((a+b)>>1); // works. overflow detected. no confusion.
		
		// unsigned operator
		System.out.println((a+b)>>>1); // works. overflow no issue. confusion.
		System.out.println(((int)(a+b))>>>1); // works. overflow no issue. confusion. 
		
		System.out.println((long)(a+b+c)); // confusion. result not clear.
		System.out.println((a+b+c)>>>1); // confusion. result not clear.
		System.out.println((long)(a+b+c+d)); // confusion. result not clear.
		System.out.println((a+b+c+d)>>>1); // confusion. result not clear.

		
    	System.out.println("___Shown how right operand is subjected to mod 32 in case of left operand an int");
		getBinaryString(2 << 11, "2 << 11");
		getBinaryString(2 << 22, "2 << 22");
		getBinaryString(2 << 30, "2 << 30");
		getBinaryString(2 << 31, "2 << 31");
		getBinaryString(2 << 32, "2 << 32");
		getBinaryString(2 << 33, "2 << 33");
		getBinaryString(2 << 44, "2 << 44");
		getBinaryString(2 << 55, "2 << 55");
		
		System.out.println("___Shown how sign extention comes into picture in case of signed right operation '>>'");
		getBinaryString(-1);
		getBinaryString(-1>>5,"-1>>5");
	}
	
	// utility methods for s.o.p.
	public static String getBinaryString(int num){
		System.out.println("For "+num+" resultant binary string is: >"+Integer.toBinaryString(num)+"< with length "+(Integer.toBinaryString(num)).length());
		return Integer.toBinaryString(num);
	}

	public static String getBinaryString(int num, String operation){
		//System.out.println(num+" in binary string is: >"+Integer.toBinaryString(num)+"< with length "+(Integer.toBinaryString(num)).length());
		System.out.println("For operation "+operation+", resultant binary string is: >"+Integer.toBinaryString(num)+"< with length "+(Integer.toBinaryString(num)).length());
		return Integer.toBinaryString(num);
	}
}
